package com.ycg.vue.aspect;

import com.ycg.vue.constant.AspectConstant;
import com.ycg.vue.context.ThreadLocalContext;
import com.ycg.vue.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;

/**
 * @Description 自动插入实体类字段
 * @Author jink
 * @Date 2024/1/18
 */
@Slf4j
@Component
@Aspect
public class AutoInsert {
    @Before(value = "execution(* com.ycg..*.mapper.*.*(..)) && @annotation(com.ycg.vue.Annotation.AutoInsert)")
    public void AutoInsert(JoinPoint joinPoint) {
        log.info("<===== AutoInsert start =====>");
        //获取参数
        Object[] args = joinPoint.getArgs();
        if (Objects.isNull(args) || args.length == 0) {
            log.warn("<===== AutoInsert warn:Not Find Args =====>");
            log.info("<===== AutoInsert end =====>");
            return;
        }
        //得到第一个参数，这也意味着，如果参数不止一个，那么只能取第一个，因此，进入切片的方法，第一个参数，必须是实体类
        Object entity = args[0];
        //获取方法签名
        MethodSignature methodsMetadata = (MethodSignature) joinPoint.getSignature();
        //获取方法
        Method method = methodsMetadata.getMethod();
        //获取注解
        com.ycg.vue.Annotation.AutoInsert annotation = method.getAnnotation(com.ycg.vue.Annotation.AutoInsert.class);
        Date now = new Date();
        String id = UUIDUtils.getUUID();
        try {
            //判断注解类型
            switch (annotation.value()) {
                case INSERT: {
                    log.info("<===== AutoInsert Type:INSERT =====>");
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_ID, String.class).invoke(entity,id);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_CREATE_BY, String.class).invoke(entity, ThreadLocalContext.getUserId());
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_UPDATE_BY, String.class).invoke(entity, ThreadLocalContext.getUserId());
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_CREATE_TIME,java.util.Date.class).invoke(entity, now);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_UPDATE_TIME, java.util.Date.class).invoke(entity, now);
                    break;
                }
                case UPDATE: {
                    log.info("<===== AutoInsert Type:UPDATE =====>");
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_UPDATE_BY, String.class).invoke(entity, ThreadLocalContext.getUserId());
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_UPDATE_TIME, java.util.Date.class).invoke(entity, now);
                    break;
                }
                case REGISTER: {
                    log.info("<===== AutoInsert Type:REGISTER =====>");
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_ID, String.class).invoke(entity, id);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_CREATE_BY, String.class).invoke(entity, id);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_UPDATE_BY, String.class).invoke(entity, id);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_CREATE_TIME, java.util.Date.class).invoke(entity, now);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_UPDATE_TIME, java.util.Date.class).invoke(entity, now);
                    break;
                }
                case LOG:{
                    log.info("<===== AutoInsert Type:SAVE_LOG =====>");
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_ID, String.class).invoke(entity,id);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_OPERATOR, String.class).invoke(entity, ThreadLocalContext.getUserId());
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_OPERATION_TIME, java.util.Date.class).invoke(entity, now);
                    entity.getClass().getDeclaredMethod(AspectConstant.SET_OPERATOR_IP, String.class).invoke(entity, ThreadLocalContext.getIp());
                    break;
                }
            }
            log.info("<===== AutoInsert end =========>");
            log.info("<===== AutoInsert success =====>");
        } catch (Exception e) {
            log.error("<===== AutoInsert error ======>");
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
